import pygame
from tinytag import TinyTag
import os
import random
from PyQt5.QtWidgets import *
from PyQt5.Qt import Qt
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QPoint
import sys
from module import *
from ui.Ui_main import Ui_MainWindow
import ui.resources_rc

class MainWin(QMainWindow):
    def __init__(self):
        super(MainWin, self).__init__()
        global totalseconds,nowplaying,currentSong,filenames,openfile,playedmusic

        # 设置边框区域宽度，在此宽度内长按鼠标并拖动可实现缩放
        self.borderWide = 10

        # 初始化窗口
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.resize(self.screenSize().width() / 1.5, self.screenSize().height() / 1.5)
        self.stateMaximized = False
        # 隐藏窗体顶部
        self.setWindowFlags(Qt.FramelessWindowHint)
        # 给combobox加上view，不加不能正常显示combobox样式
        self.ui.comboBoxMode.setView(QListView())
        # 边框样式
        self.ui.frame.setFrameStyle(QFrame.Panel)

        # 创建菜单栏
        self.createMenus()

        # 事件绑定
        self.signalConnect()

        # 初始化
        self.ui.pBtnList.click()
        self.ui.labelAllMusic.setText("全部音乐（0）")  # 标题中的音乐数

        timecount=QtCore.QTimer(self)
        totalseconds=0
        timecount.timeout.connect(self.countTime)
        timecount.start(10)
        nowplaying=False
        currentSong=None

        timer=QtCore.QTimer(self)
        timer.timeout.connect(self.timerUpdate)
        timer.start(1000)
        filenames=[]
        openfile=r'C:\Users\zhaizhengda'
        playedmusic=[]
        self.ui.widgetPlay.hide()

        # 设置鼠标跟踪判断默认值
        self.initDrag()

        # 设置鼠标追踪（从子组件依次向父组件设置追踪）
        self.ui.frame.setMouseTracking(True)
        self.ui.centralwidget.setMouseTracking(True)
        self.setMouseTracking(True)  # 设置widget鼠标跟踪

        self.tableWidgetInit()  # 表格初始化

    def createMenus(self):
        '''
        创建菜单
        '''
        # 文件菜单
        menuFile = QMenu('文件')
        self.actionOpenHolder = menuFile.addAction('打开文件夹')
        self.actionOpenFile = menuFile.addAction('打开文件')
        self.actionExit = menuFile.addAction('退出')
        self.ui.pBtnFile.setMenu(menuFile)
        # 帮助菜单
        menuHelp = QMenu('帮助')
        self.actionHelp = menuHelp.addAction('使用帮助')
        self.actionAbout = menuHelp.addAction('关于')
        self.ui.pBtnHelp.setMenu(menuHelp)  # pBtnHelp作为菜单

        menuFile.setStyleSheet(menustylesheet)
        menuHelp.setStyleSheet(menustylesheet)

        # 事件绑定
        self.actionOpenHolder.triggered.connect(self.openHolder)
        self.actionOpenFile.triggered.connect(self.openFile)
        self.actionExit.triggered.connect(self.close)
        self.actionHelp.triggered.connect(self.findHelp)
        self.actionAbout.triggered.connect(self.showAbout)

        # 调整menu下拉菜单宽度
        menuHelp.setFixedWidth(menuHelp.sizeHint().width() + 20)
        menuFile.setFixedWidth(menuFile.sizeHint().width() + 20)

    def signalConnect(self):
        self.ui.pBtnSmall.clicked.connect(self.showMinimized)
        self.ui.pBtnBig.clicked.connect(self.maximumStateChange)
        self.ui.pBtnClose.clicked.connect(self.close)

        self.ui.pBtnOpenFiles.clicked.connect(self.openHolder)
        self.ui.pBtnOpenFile.clicked.connect(self.openFile)
        self.ui.pBtnList.clicked.connect(self.changeToList)
        self.ui.pBtnPic.clicked.connect(self.changeToPic)
        self.ui.pBtnSearch.clicked.connect(self.search)

        self.ui.pBtnPlay.clicked.connect(self.playAndStop)
        self.ui.pBtnLast.clicked.connect(self.playLast)
        self.ui.pBtnNext.clicked.connect(self.playNext)

    def tableWidgetInit(self):
        # 表格设置
        self.ui.tableWidgetList.horizontalHeader().setMinimumHeight(30)  # 表头高度
        # 每次选择一个
        self.ui.tableWidgetList.setSelectionMode(QAbstractItemView.SingleSelection)
        # 设置列宽模式
        for i in range(6):
            self.ui.tableWidgetList.resizeColumnToContents(i)
        self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 自适应窗口宽度
        self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)  # 第一列自适应内容
        # 初始化设置信号
        self.ui.tableWidgetList.setRowCount(0)
        self.ui.tableWidgetList.itemClicked.connect(self.playListSong)

        self.ui.tableWidgetPic.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 自适应窗口宽度
        for i in range(5):
            self.ui.tableWidgetPic.resizeColumnToContents(i)
        self.ui.tableWidgetPic.horizontalHeader().setMinimumSectionSize(240)
        self.ui.tableWidgetPic.verticalHeader().setDefaultSectionSize(300)

    def timerUpdate(self):
        time=QtCore.QDateTime().currentDateTime()
        timeshow=time.toString("yyyy-MM-dd hh:mm:ss dddd")
        self.ui.labelTimeDate.setText(timeshow)

    def openFile(self):
        global filenames,openfile
        openfilenames,_=QFileDialog.getOpenFileNames(self,"打开文件",openfile,"Audio files(*.mp3 *.flac *.wav *.ogg)")
        for file in openfilenames:
            if (file in filenames)==False:
                filenames.append(file)
        self.showMusic(filenames)

    def openHolder(self):
        global filenames,openfile
        openfile=QFileDialog.getExistingDirectory(self,"选择文件夹",openfile)
        openfilelist=[]
        for _,_,files in os.walk(openfile):
            for file in files:
                if file.split('.')[-1] in ['mp3','flac','wav','ogg']:
                    openfilelist.append(openfile+'/'+file)
        for file in openfilelist:
            if (file in filenames)==False:
                filenames.append(file)
        self.showMusic(filenames)

    def findHelp(self):
        self.helpwindow=Message()
        self.helpwindow.ui.labelMainMessage.setText("作者联系方式：\n微信：zzd112344\n邮箱：xqsx44zzd@126.com")
        self.helpwindow.ui.labelTitle.setText("获取帮助")
        self.helpwindow.ui.pBtnCancel.hide()
        self.helpwindow.show()
        self.helpwindow.ui.pBtnOK.clicked.connect(self.helpwindow.close)

    def showAbout(self):
        self.aboutwindow=Message()
        self.aboutwindow.ui.labelMainMessage.setText("音乐播放器V1.0\n作者：计205 翟正达 42021029")
        self.aboutwindow.ui.labelTitle.setText("关于")
        self.aboutwindow.ui.pBtnCancel.hide()
        self.aboutwindow.show()
        self.aboutwindow.ui.pBtnOK.clicked.connect(self.aboutwindow.close)

    def playListSong(self):
        row=self.ui.tableWidgetList.currentRow()
        self.playchoosedSong(row)

    def playchoosedSong(self,row):
        global playlastmode
        playlastmode=False
        self.playMusic(row)

    def playMusic(self, row):
        global filenames,seconds,totalseconds,start,musictext,currentSong,nowplaying,playedmusic,playlastmode
        music=filenames[row]
        currentSong=row
        nowplaying=True
        if playlastmode==False:
            playedmusic.append(row)
        self.ui.widgetPlay.show()
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/resources/暂停.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.ui.pBtnPlay.setIcon(icon)
        try:
            musictext=open(''.join(music.split('.')[:-1])+".lrc",encoding="utf-8").readlines()
            i=-1
            for line in musictext:
                i=i+1
                if len(line)<10: continue
                if line[0:4]=="[00:":
                    start=i
                    break
        except:
            self.ui.labelMusicWord.setText("没有歌词")
            musictext=None

        info=TinyTag.get(music,image=True)
        bytes=info.get_image()
        if bytes!=None:
            qpic=QtGui.QImage()
            qpic.loadFromData(bytes)
            qpicnew=qpic.scaled(150,150,transformMode=QtCore.Qt.SmoothTransformation)
            self.ui.labelMusicPic.setPixmap(QtGui.QPixmap.fromImage(qpicnew))
        else:
            qpic=QtGui.QPixmap(":/resources/没有封面.jpg")
            qpicnew=qpic.scaled(150,150,transformMode=QtCore.Qt.SmoothTransformation)
            self.ui.labelMusicPic.setPixmap(qpicnew)
        self.ui.labelMusicName.setText(info.title if info.title!=None and info.title!='' else ''.join(music.split('/')[-1].split('.')[:-1]))
        self.ui.labelMusicSinger.setText(info.artist if info.artist!=None and info.artist!='' else "未知歌手")
        m,s=divmod(info.duration,60)
        self.ui.labelTimeTotal.setText("%02d:%02d" % (m,s))
        
        pygame.mixer.init()
        pygame.mixer.music.load(music.encode())
        seconds=0
        totalseconds=int(info.duration)
        pygame.mixer.music.play()

    def countTime(self):
        global seconds,totalseconds,start,musictext
        if totalseconds!=0:
            self.ui.horizontalSlider.setValue(seconds/totalseconds)
            m,s=divmod(seconds,6000)
            self.ui.labelTimeNow.setText("%02d:%02d" % (m,s/100))
            try:
                if int(musictext[start+1][2])*6000 + float(musictext[start+1][4:9])*100<seconds:
                    start=start+1
                i=(10 if musictext[start][10]!=']' else 11)
                self.ui.labelMusicWord.setText(musictext[start][i:-1])
            except:
                pass
            if seconds/100>=totalseconds:
                totalseconds=0
                self.playNext()
            seconds=seconds+1

    def playAndStop(self):
        global nowplaying,totalseconds,currentSong,currenttotal
        icon = QtGui.QIcon()
        if nowplaying==True:
            icon.addPixmap(QtGui.QPixmap(":/resources/播放.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            pygame.mixer.music.pause()
            currenttotal=totalseconds
            totalseconds=0
            nowplaying=False
        elif currentSong!=None:
            icon.addPixmap(QtGui.QPixmap(":/resources/暂停.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            pygame.mixer.music.unpause()
            totalseconds=currenttotal
            nowplaying=True
        self.ui.pBtnPlay.setIcon(icon)

    def playNext(self):
        global currentSong,filenames,playlastmode
        try:
            playMode=self.ui.comboBoxMode.currentText()
            playlastmode=False
            if playMode=="单曲循环":
                self.playMusic(currentSong)
            if playMode=="随机播放":
                self.playMusic(random.randint(0,len(filenames)))
            if playMode=="顺序播放":
                self.playMusic(currentSong+1 if currentSong!=len(filenames)-1 else 0)
        except:
            pass

    def playLast(self):
        global playedmusic,playlastmode
        if len(playedmusic)>1:
            musiclastplay=playedmusic[-2]
            playedmusic=playedmusic[:-1]
            playlastmode=True
            self.playMusic(musiclastplay)

    def search(self):
        searchtext=self.ui.lineEditSearch.text()
        for i in range(0,self.ui.tableWidgetList.rowCount()):
            for j in range(1,self.ui.tableWidgetList.columnCount()):
                self.ui.tableWidgetList.item(i,j-1).setForeground(QtCore.Qt.white)
        if searchtext!='':
            items=self.ui.tableWidgetList.findItems(searchtext,QtCore.Qt.MatchContains)
            if items!=None:
                for item in items:
                    item.setForeground(QtCore.Qt.red)

    def changeToPic(self):
        self.ui.widgetShowPic.show()
        self.ui.widgetShowList.hide()

    def changeToList(self):
        self.ui.widgetShowPic.hide()
        self.ui.widgetShowList.show()

    def showMusic(self, musicList):
        while self.ui.tableWidgetList.rowCount()>0:
            self.ui.tableWidgetList.removeRow(0)
        for row, music in enumerate(musicList):
            info=TinyTag.get(music,image=True)
            musicInfoList = [None for _ in range(5)]
            musicInfoList[0] = row
            musicInfoList[1] = (info.title if info.title!=None and info.title!='' else ''.join(music.split('/')[-1].split('.')[:-1]))
            musicInfoList[2] = (info.artist if info.artist!=None and info.artist!='' else "未知歌手")
            musicInfoList[3] = (info.album if info.album!=None and info.album!='' else "未知专辑")
            m,s=divmod(info.duration,60)
            musicInfoList[4] = "%02d:%02d" % (m,s)
            self.addRow(row, musicInfoList)

        while self.ui.tableWidgetPic.rowCount()>0:
            self.ui.tableWidgetPic.removeRow(0)
        for row, music in enumerate(musicList):
            self.addPicItem(row, music)

        self.ui.labelAllMusic.setText(f"全部音乐（{len(musicList)}）")  # 修改标题中的项目数

    def addRow(self, row, rowData: list):
        '''
        添加一行数据
        '''
        self.ui.tableWidgetList.setRowCount(row + 1)  # 为表格扩充一行

        # 添加数据
        item = QTableWidgetItem('%02d' % (row + 1))
        item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.ui.tableWidgetList.setItem(row, 0, item)
        for i in range(len(rowData) - 1):
            item = QTableWidgetItem(str(rowData[i + 1]))
            item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.ui.tableWidgetList.setItem(row, i + 1, item)

        widgetMusicBtn = ListButtonWidget(row)
        widgetMusicBtn.signal_delItem.connect(self.deleteMusic)  # 事件绑定
        widgetMusicBtn.signal_play.connect(self.playchoosedSong)
        self.ui.tableWidgetList.setCellWidget(row, 5, widgetMusicBtn)

    def addPicItem(self, row, music):
        '''
        添加一个缩略图数据
        '''
        if self.ui.tableWidgetPic.rowCount() < row // 5 + 1:
            self.ui.tableWidgetPic.setRowCount(row // 5 + 1)  # 为表格扩充一行

        # 添加数据
        picWidget = PicShowWidget(row, music)
        picWidget.signalDelPicItem.connect(self.deleteMusic)  # 事件绑定
        picWidget.signalPlayPicItem.connect(self.playchoosedSong)
        self.ui.tableWidgetPic.setCellWidget(row // 5, row % 5, picWidget)

    def deleteMusic(self, musicnumber):
        '''
        根据行数删除
        '''
        self.askwindow=Message(musicnumber)
        self.askwindow.ui.labelMainMessage.setText("删除列表中文件或是同时删除本地文件？")
        self.askwindow.ui.pBtnCancel.setText("仅删除列表中文件")
        self.askwindow.ui.pBtnOK.setText("同时删除本地文件")
        self.askwindow.show()
        self.askwindow.signalchoosecancel.connect(self.deleteListMusic)
        self.askwindow.signalchooseyes.connect(self.deleteLocalMusic)

    def deleteLocalMusic(self,row):
        global filenames
        os.remove(filenames[row])
        self.deleteListMusic(row)
    
    def deleteListMusic(self,row):
        global filenames
        self.askwindow.close()
        del filenames[row]
        self.showMusic(filenames)

    def screenSize(self):
        screen = QDesktopWidget().screenGeometry()
        return screen

    def maximumStateChange(self):
        '''
        窗口最大化与恢复
        '''
        if self.stateMaximized:
            self.showNormal()
            self.stateMaximized = False
        else:
            self.showMaximized()
            self.stateMaximized = True

    # 窗口拖拽事件
    def initDrag(self):
        # 设置鼠标跟踪判断扳机默认值
        self.moveDrag = False
        self.cornerDrag = False
        self.bottomDrag = False
        self.rightDrag = False

    def resizeEvent(self, QResizeEvent):
        # 重新调整边界范围以备实现鼠标拖放缩放窗口大小，采用三个列表生成式生成三个列表
        self.rightRect = [QPoint(x, y) for x in range(self.width() - self.borderWide, self.width() + 1)
                          for y in range(1, self.height() - self.borderWide)]
        self.bottomRect = [QPoint(x, y) for x in range(1, self.width() - self.borderWide)
                           for y in range(self.height() - self.borderWide, self.height() + 1)]
        self.cornerRect = [QPoint(x, y) for x in range(self.width() - self.borderWide, self.width() + 1)
                           for y in range(self.height() - self.borderWide, self.height() + 1)]

    def mousePressEvent(self, event):
        # 重写鼠标点击的事件
        if (event.button() == Qt.LeftButton) and (event.pos() in self.cornerRect):
            # 鼠标左键点击右下角边界区域
            self.cornerDrag = True
            event.accept()
        elif (event.button() == Qt.LeftButton) and (event.pos() in self.rightRect):
            # 鼠标左键点击右侧边界区域
            self.rightDrag = True
            event.accept()
        elif (event.button() == Qt.LeftButton) and (event.pos() in self.bottomRect):
            # 鼠标左键点击下侧边界区域
            self.bottomDrag = True
            event.accept()
        elif (event.button() == Qt.LeftButton) and (event.y() < self.ui.widgetTop.height()):
            # 鼠标左键点击标题栏区域
            self.moveDrag = True
            self.moveDragPosition = event.globalPos() - self.pos()
            event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        # 判断鼠标位置切换鼠标手势
        if QMouseEvent.pos() in self.cornerRect:
            self.setCursor(Qt.SizeFDiagCursor)
        elif QMouseEvent.pos() in self.bottomRect:
            self.setCursor(Qt.SizeVerCursor)
        elif QMouseEvent.pos() in self.rightRect:
            self.setCursor(Qt.SizeHorCursor)
        else:
            self.setCursor(Qt.ArrowCursor)
        # 当鼠标左键点击不放及满足点击区域的要求后，分别实现不同的窗口调整
        if Qt.LeftButton and self.rightDrag:
            # 右侧调整窗口宽度
            self.resize(QMouseEvent.pos().x(), self.height())
            QMouseEvent.accept()
        elif Qt.LeftButton and self.bottomDrag:
            # 下侧调整窗口高度
            self.resize(self.width(), QMouseEvent.pos().y())
            QMouseEvent.accept()
        elif Qt.LeftButton and self.cornerDrag:
            # 右下角同时调整高度和宽度
            self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y())
            QMouseEvent.accept()
        elif Qt.LeftButton and self.moveDrag:
            # 标题栏拖放窗口位置
            self.move(QMouseEvent.globalPos() - self.moveDragPosition)
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        # 鼠标释放后，各扳机复位
        self.moveDrag = False
        self.cornerDrag = False
        self.bottomDrag = False
        self.rightDrag = False

if __name__ == '__main__':
    # 自适应高分辨率屏幕
    QtCore.QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)  # 适应windows缩放
    app = QApplication(sys.argv)
    myWin = MainWin()
    myWin.show()
    sys.exit(app.exec_())
